/**
 * 抖音加热数据抓取工具栏
 */

import { StyleProvider } from "@ant-design/cssinjs"
import { FormOutlined } from "@ant-design/icons"
import { nextTick } from "@mswjs/interceptors/src/utils/nextTick"
import { Button, Modal } from "antd"
import cssText from "data-text:~/assets/css/dataScreenV2.css"
import antdResetCssText from "data-text:antd/dist/reset.css"
import moment from "moment"
import type {
  PlasmoCSConfig,
  PlasmoGetInlineAnchor,
  PlasmoGetShadowHostId
} from "plasmo"
import React, { useEffect, useMemo, useState } from "react"
import * as xlsx from "xlsx"

import { usePort } from "@plasmohq/messaging/hook"
import { useStorage } from "@plasmohq/storage/dist/hook"

import { ThemeProvider } from "~theme"
import DyShopScoreDataDetailModal from "~ui_components/DyShopScoreDataDetailModal"
import { _callApi } from "~utils/tools"

// 注入配置
export const config: PlasmoCSConfig = {
  matches: [
    // 抖音加热订单数据页面地址
    "https://channels.weixin.qq.com/promote/pages/platform/live/home*"
  ],
  run_at: "document_end",
  all_frames: true
}

// 注入样式
export const getStyle = () => {
  const style = document.createElement("style")
  style.textContent = cssText + antdResetCssText
  return style
}

// 注入的shadow dom的id
export const HOST_ID = "dy-shop-heat-data-tool"
export const getShadowHostId: PlasmoGetShadowHostId = () => HOST_ID

// export const getRootContainer = () => document.getElementById("app")
export const getInlineAnchor: PlasmoGetInlineAnchor = async () => {
  return {
    element: document.querySelector("span[class^='text-2xl']"),
    insertPosition: "afterend"
  }
}

const DyShopHeatDataToolbar: React.FC = () => {
  // <a>元素 sate
  const [nextPageBtn, setNextPageBtn] = useState<HTMLAnchorElement | null>(null)
  // 是否显示详情弹窗
  const [showDetailModal, setShowDetailModal] = useState(false)
  // 进度文字列表
  const [processTxt, setProcessTxt] = useState<string[]>([])
  // 数据总量
  const [totalCount, setTotalCount] = useState(0)
  // 订单数据记录
  const [orderDetail, setOrderDetail] = useState<{}>({})
  // 获取数据状态
  const [isFetching, setIsFetching] = useState(false)
  // 分页数据拦截结束状态, 为true时触发处理，useEffect监听
  const [isPageFetchEnd, setIsPageFetchEnd] = useState(false)

  // 处理加热订单列表请求
  const heatOrderListRequestFilter = async (
    url: string,
    params: any,
    response: any
  ) => {
    // 正则匹配url https://channels.weixin.qq.com/promote/api/web/transfer/MMFinderPromotionLiveDspApiSvr/searchLivePromotionOrderList
    const urlReg = new RegExp(
      `^https://channels.weixin.qq.com/promote/api/web/transfer/MMFinderPromotionLiveDspApiSvr/searchLivePromotionOrderList`
    )
    if (!urlReg.test(url)) return false
    // 查询日期范围
    const queryDate = getFetchDateRange()
    // 请求日期范围
    const requestStartDate = params["createTsMin"]
      ? moment.unix(Number(params["createTsMin"])).format("YYYY-MM-DD")
      : ""
    const requestEndDate = params["createTsMax"]
      ? moment.unix(Number(params["createTsMax"])).format("YYYY-MM-DD")
      : ""
    // 如果日期不匹配，则不拦截
    if (
      queryDate["start"] !== requestStartDate ||
      queryDate["end"] !== requestEndDate
    )
      return false
    // 开始数据拦截
    const { data } = response
    // console.log("订单列表数据拦截", data)
    // 页码
    const pageNo = params["page"]
    // 总单量
    const total = data["total"] || 0
    // 订单列表
    const orderList = data["orderList"] || []

    setTotalCount(total)
    if (pageNo == 1) {
      // 第一页
      // 订单信息初始化记录
      setOrderDetail({})
    }
    // 记录订单信息
    const orderMap = orderList.reduce((map: {}, order: any) => {
      map[order.promotionId] = {}
      return map
    }, {})
    setOrderDetail((prev) => ({
      ...prev,
      ...orderMap
    }))
    // 设置标记点
    setIsPageFetchEnd(true)
    return true
  }

  // 计算未获取详情的订单数
  const waitForFetchDetailOrderCount = useMemo(() => {
    let count = 0
    for (const key in orderDetail) {
      if (Object.keys(orderDetail[key]).length === 0) {
        count++
      }
    }
    return count
  }, [orderDetail])

  // 获取订单查询日期范围
  const getFetchDateRange = () => {
    const dateInputList: NodeListOf<HTMLInputElement> =
      document.querySelectorAll("dl.finder-ui-desktop-picker__date-range input")
    if (dateInputList.length == 2) {
      return {
        start: dateInputList[0].value,
        end: dateInputList[1].value
      }
    } else {
      return { start: "", end: "" }
    }
  }

  // 网络请求拦截事件处理
  const eventFunc = (
    event: CustomEvent<{
      url: string
      response: any
      params: any
    }>
  ) => {
    // 请求处理器列表
    const requestHandlers = [heatOrderListRequestFilter]
    const { url, params, response } = event.detail
    requestHandlers.forEach((handler) => {
      handler(url, params, response).then()
    })
  }

  // 监控下一页元素
  const observerNextPageBtn = () => {
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        // 检查新增的节点
        mutation.addedNodes.forEach((node: Element) => {
          if (node.nodeType === 1) {
            // 确保是元素节点
            // 查找目标元素
            if (node.tagName === "A" && node.textContent === "下一页") {
              // 如果为<a>且内容为“下一页”，获取目标元素
              setNextPageBtn(node as HTMLAnchorElement)
            } else {
              // 非<a>，采用查找方式获取
              const targetElement = node.querySelector(
                "a.finder-ui-desktop-btn"
              )
              if (targetElement && targetElement.textContent === "下一页") {
                // 获取目标元素
                setNextPageBtn(targetElement as HTMLAnchorElement)
              }
            }
          }
        })

        // 检查删除的节点
        mutation.removedNodes.forEach((node: Element) => {
          if (node.nodeType === 1) {
            // 确保是元素节点
            // 查找目标元素
            if (node.tagName === "A" && node.textContent === "下一页") {
              // 如果为<a>且内容为“下一页”，清空目标元素
              setNextPageBtn(null)
            } else {
              // 非<a>，采用查找方式获取
              const targetElement = node.querySelector(
                "a.finder-ui-desktop-btn"
              )
              if (targetElement && targetElement.textContent === "下一页") {
                // 获取目标元素
                setNextPageBtn(null)
              }
            }
          }
        })
      })
    })

    // 配置观察选项
    const config = { childList: true, subtree: true }

    // 选择要观察的目标节点（例如 document.body）
    const targetNode = document.body

    // 开始观察
    observer.observe(targetNode, config)
  }

  // 处理打开弹窗事件
  const handleOpenDetailModal = () => {
    setShowDetailModal(true)
  }

  // 处理关闭弹窗事件
  const handleCloseDetailModal = () => {
    setShowDetailModal(false)
  }
  // 记录进度文字
  const handleRecordProcessTxt = (txt: string) => {
    // 当前时间
    const curTime = moment().format("YYYY-MM-DD HH:mm:ss")
    // 当前文字长度
    const curLen = processTxt.length
    // 组织记录内容格式
    const formatTxt = `[${curLen + 1}-${curTime}]:${txt}`
    // 将最新的Txt放到processTxt列表的首位
    nextTick(() => {
      setProcessTxt((prev) => [formatTxt, ...prev])
    })
  }

  // 处理开始循环分页获取订单列表
  const handleStartFetchOrderList = async () => {
    handleRecordProcessTxt("开始抓取数据")
    // 检查当前页是否为第一页，如果不是则需要回到第一页开始
    // 当前页label
    const curPageLabel = document.querySelector(
      "label.finder-ui-desktop-pagination__num_current"
    )
    if (curPageLabel.textContent !== "1") {
      // 提示手动跳转到第一页
      const pageBtnList: NodeListOf<HTMLElement> = document.querySelectorAll(
        "label.finder-ui-desktop-pagination__num"
      )
      if (pageBtnList.length > 0) {
        pageBtnList[0].click()
      }
    }
    // 设置等待分页数据拦截获取结束状态
    setIsPageFetchEnd(false)
    // 设置数据获取状态
    setIsFetching(true)
    // 点击下一页
    if (nextPageBtn) {
      handleRecordProcessTxt('点击"下一页"按钮,等待数据获取')
      nextPageBtn.click()
    }
  }

  // 订单详情html数据解析
  const _parseOrderDetailHtmlData = (node: HTMLElement) => {
    const output = {}
    // 加热信息处理
    const heatInfoNodes = node.querySelectorAll("div.user-profile > div > div")
    heatInfoNodes.forEach((_node: HTMLElement, idx) => {
      const txt = _node.textContent
      if (idx === 0) {
        output["直播间"] = txt
      } else {
        const txtSplit = txt.split("：")
        if (txtSplit.length === 2) {
          output[txtSplit[0].trim()] = txtSplit[1]
        }
      }
    })
    const heatInfoRows = node.querySelectorAll("div.table-row")
    heatInfoRows.forEach((_node: HTMLElement) => {
      const cellDivs = _node.querySelectorAll("div.table-cell")
      cellDivs.forEach((_cellNode) => {
        const contentDivs = _cellNode.querySelectorAll("div")
        if (contentDivs.length >= 2) {
          const key = contentDivs[0].textContent.trim()
          output[key] = contentDivs[1].querySelector("span").textContent.trim()
        }
      })
    })
    // 加热效果处理
    const heatEffectBlocks = node.querySelectorAll(
      "div.data-item-container > div.mb-12"
    )
    heatEffectBlocks.forEach((_node) => {
      const contentDivs = _node.querySelectorAll("div")
      if (contentDivs.length >= 2) {
        const key = contentDivs[0].textContent.trim()
        output[key] = contentDivs[1].querySelector("span").textContent.trim()
      }
    })

    return output
  }

  // 处理抓取单个订单详情数据
  const handleFetchOrderDetail = (promotionId: string) => {
    return new Promise(async (resolve) => {
      const detailUrl = `https://channels.weixin.qq.com/promote/pages/platform/live/live-promote-order-detail?id=${promotionId}`
      // 使用iframe获取
      const iframe = document.createElement("iframe")
      // 将 iframe 移动到视口之外
      iframe.style.position = "absolute"
      iframe.style.left = "-9999px"
      iframe.src = detailUrl
      iframe.id = "fetch-iframe-" + promotionId
      // 处理 iframe 加载错误
      iframe.onerror = () => {
        resolve(new Error("Failed to load iframe"))
      }

      // iframe 加载完成事件
      iframe.onload = () => {
        const targetNode = iframe.contentDocument
        if (!targetNode) {
          resolve(new Error("Failed to access iframe content"))
          return
        }

        // 页面数据观察监听
        const observer = new MutationObserver((mutations) => {
          mutations.forEach((mutation) => {
            // 检查新增的节点
            mutation.addedNodes.forEach((node: HTMLElement) => {
              if (node.nodeType === 1) {
                const queryNodes = node.querySelectorAll(
                  "div.container-center > div.flex-auto  div.user-profile > div > div"
                )
                if (queryNodes.length > 0) {
                  const parseData = _parseOrderDetailHtmlData(
                    targetNode.querySelector(
                      "div.container-center > div.flex-auto"
                    ) as HTMLElement
                  )
                  observer.disconnect()
                  iframe.remove()
                  resolve(parseData)
                }
              }
            })
          })
        })

        // 配置观察选项
        const config = { childList: true, subtree: true }

        // 开始观察
        observer.observe(targetNode, config)
      }
      document.body.appendChild(iframe)
    })
  }

  // 处理抓取订单列表事件
  const handleFetchOrderListData = async () => {
    // 如果订单总数大于20个
    if (totalCount > 20) {
      // 开始抓取订单列表数据
      await handleStartFetchOrderList()
    }
  }

  // 处理抓取订单详情事件
  const handleFetchOrderDetailData = async () => {
    // 判断订单列表是否和总量一样
    // if(totalCount != waitForFetchDetailOrderCount) return false
    // 开始循环抓取
    handleRecordProcessTxt("开始抓取订单详情数据...")
    const promotionIds = Object.keys(orderDetail)
    const tempRecord = {}
    for (let i = 0; i < promotionIds.length; i++) {
      const orderId = promotionIds[i]
      handleRecordProcessTxt(`订单:${orderId}, 抓取详情中...`)
      tempRecord[orderId] = await handleFetchOrderDetail(orderId)
      handleRecordProcessTxt(
        `订单:${promotionIds[i]}, 完成抓取。 剩余${
          promotionIds.length - i - 1
        }/${promotionIds.length}`
      )
    }
    // 写入orderDetail
    setOrderDetail(tempRecord)
    return true
  }

  // 处理导出订单数据事件
  const handleExportOrderDetailData = async () => {
    const header = []
    const data = []
    for (const key in orderDetail) {
      data.push(orderDetail[key])
    }
    if (data.length > 0) {
      for (const key in data[0]) {
        header.push(key)
      }
    }
    // 导出为excel文件
    const wb = xlsx.utils.book_new()
    const ws = xlsx.utils.json_to_sheet(data, { header: header })
    xlsx.utils.book_append_sheet(wb, ws, "sheet1")
    const fileName = `视频号加热订单数据_${moment().format("YYYY-MM-DD")}.xlsx`
    xlsx.writeFile(wb, fileName)
  }

  // 分页处理循环处理监听
  useEffect(() => {
    if (isPageFetchEnd && isFetching) {
      if (nextPageBtn) {
        handleRecordProcessTxt("已获取列表数据，等待下一页数据")
        setIsPageFetchEnd(false)
        nextPageBtn.click()
      } else {
        handleRecordProcessTxt("已完成订单列表数据抓取处理")
      }
    }
  }, [isPageFetchEnd, isFetching])

  useEffect(() => {
    // testFunc().then()
    // 开启元素监听
    observerNextPageBtn()
    // 注册事件监听
    window.addEventListener("hijackEvent", eventFunc)
    // 卸载事件监听
    return () => {
      window.removeEventListener("hijackEvent", eventFunc)
    }
  }, [])

  return (
    <ThemeProvider>
      <StyleProvider container={document.getElementById(HOST_ID).shadowRoot}>
        <div className={"wx-heat-data-wrapper"}>
          <Button type={"primary"} onClick={handleOpenDetailModal}>
            数据抓取
          </Button>
          {/*数据抓取管理弹窗*/}
          <Modal
            key={"wx-heat-data-detail-modal"}
            width={950}
            className={"shop-score-data-detail-modal-wrapper"}
            open={showDetailModal}
            footer={false}
            onCancel={handleCloseDetailModal}
            mask={false}
            title={"视频号加热订单数据抓取"}
            getContainer={false}
            maskClosable={false}>
            <div className={"ss-process-txt-wrapper"}>
              {/*循环显示文字*/}
              {processTxt.map((txt, index) => (
                <div key={"pct" + index} className={"txt-content"}>
                  {txt}
                </div>
              ))}
            </div>
            <div className={"ss-footer-wrapper"}>
              <div className={"ss-left"}>
                <div>数据总量: {totalCount}</div>
                <div>待获取详情的订单数: {waitForFetchDetailOrderCount}</div>
              </div>
              <div className={"ss-right"}>
                <Button size={"small"} onClick={handleFetchOrderDetailData}>
                  抓取详情
                </Button>
                <Button size={"small"} onClick={handleFetchOrderListData}>
                  抓取列表
                </Button>
                <Button size={"small"} onClick={handleExportOrderDetailData}>
                  导出
                </Button>
              </div>
            </div>
          </Modal>
        </div>
      </StyleProvider>
    </ThemeProvider>
  )
}

export default DyShopHeatDataToolbar
